PdosPlotΒΆ
[1]:
import sisl
import sisl.viz
# This is just for convenience to retreive files
siesta_files = sisl._environ.get_environ_variable("SISL_FILES_TESTS") / "sisl" / "io" / "siesta"
We are going to get the PDOS from a SIESTA .PDOS file, but we could get it from a hamiltonian as well.
[2]:
plot = sisl.get_sile(siesta_files / "SrTiO3.PDOS").plot(Erange=[-10,10])
By default, a PDOS plot shows the total density of states:
[3]:
plot
PDOS requestsΒΆ
Thereβs a very important setting in the PdosPlot: requests. This setting expects a list of PDOS requests, where each request is a dictionary that can specify - species - atoms - orbitals (the orbital name) - n, l, m (the quantum numbers) - Z (the Z shell of the orbital) - spin
involved in the PDOS line that you want to draw. Apart from that, a request also accepts the name, color, linewidth and dash keys that manage the aesthetics of the line and normalize, which indicates if the PDOS should be normalized (divided by number of orbitals).
Here is an example of how to use the requests setting to create a line that displays the Oxygen 2p PDOS:
[4]:
plot.update_settings(requests=[{"name": "My first PDOS (Oxygen)", "species": ["O"], "n": 2, "l": 1}])
# or (it's equivalent)
plot.update_settings(requests=[{
"name": "My first PDOS (Oxygen)", "species": ["O"],
"orbitals": ["2pzZ1", "2pzZ2", "2pxZ1", "2pxZ2", "2pyZ1", "2pyZ2"]
}])
And now we are going to create three lines, one for each species
[5]:
plot.update_settings(requests=[
{"name": "Oxygen", "species": ["O"], "color": "darkred", "dash": "dash", "normalize": True},
{"name": "Titanium", "species": ["Ti"], "color": "grey", "linewidth": 3, "normalize": True},
{"name": "Sr", "species": ["Sr"], "color": "green", "normalize": True},
], Erange=[-5, 5])
Itβs interesting to note that the atoms key of each request accepts the same possibilities as the atoms argument of the Geometry methods. Therefore, you can use indices, categories, dictionaries, stringsβ¦
For example:
[6]:
# Let's import the AtomZ and AtomOdd categories just to play with them
from sisl.geom import AtomZ, AtomOdd
plot.update_settings(requests=[
{"atoms": [0,1], "name": "Atoms 0 and 1"},
{"atoms": {"Z": 8}, "name": "Atoms with Z=8"},
{"atoms": AtomZ(8) & ~ AtomOdd(), "name": "Oxygens with even indices"}
])
Easy and fast DOS splittingΒΆ
As you might have noticed, sometimes it might be cumbersome to build all the requests you want. If your needs are simple and you donβt need the flexibility of defining every parameter by yourself, there is a set of methods that will help you explore your PDOS data faster than ever before. These are: split_DOS, split_requests, update_requests, remove_requests and add_requests.?
Letβs begin with split_DOS. As you can imagine, this method splits the density of states:
[7]:
plot.split_DOS()
By default, it splits on the different species, but you can use the on argument to change that.
[8]:
plot.split_DOS(on="atoms")
Now we have the contribution of each atom.
But here comes the powerful part: split_DOS accepts as keyword arguments all the keys that a request accepts. Then, it adds that extra constrain to the splitting by adding the value to each request. So, if we want to get the separate contributions of all oxygen atoms, we can impose an extra constraint on species:
[9]:
plot.split_DOS(on="atoms", species=["O"], name="Oxygen $atoms")
and then we have only the oxygen atoms, which are all equivalent.
Note that we also set a name for all requests, with the additional twist that we used the templating supported by split_DOS. If you are splitting on parameter, you can use $parameter inside your name and the method will replace it with the value for each request. In this case parameter was atoms, but it could be anything you are splitting the DOS on.
You can also exclude some values of the parameter you are splitting on:
[10]:
plot.split_DOS(on="atoms", exclude=[1,3])
Or indicate the only values that you want:
[11]:
plot.split_DOS(on="atoms", only=[0,2])
Finally, if you want to split on multiple parameters at the same time, you can use + between different parameters. For example, to get all the oxygen orbitals:
[12]:
plot.split_DOS(on="n+l+m", species=["O"], name="Oxygen")
Managing existing requestsΒΆ
Not only you can create requests easily with split_DOS, but itβs also easy to manage the requests that you have created.
The methods that help you accomplish this are split_requests, update_requests, remove_requests. All three methods accept an undefined number of arguments that are used to select the requests you want to act on. You can refer to requests by their name (using a str) or their position (using an int). Itβs very easy to understand with examples. Then, keyword arguments depend on the functionality of each method.
For example, letβs say that we have splitted the DOS on species
[13]:
plot.split_DOS(name="$species")
and we want to remove the Sr and O lines. Thatβs easy:
[14]:
plot.remove_requests("Sr", 2)
We have indicated that we wanted to remove the request with name "Sr" and the 2nd request. Simple, isnβt it?
Now that we know how to indicate the requests that we want to act on, letβs use it to get the total Sr contribution, and then the Ti and O contributions splitted by n and l.
It sounds difficult, but itβs actually not. Just split the DOS on species:
[15]:
plot.split_DOS(name="$species", normalize=True)
And then use split_requests to split only the requests that we want to split:
[16]:
plot.split_requests("Sr", 2, on="n+l", dash="dot")
Notice how weβve also set dash for all the requests that split_requests has generated. We can do this because split_requests works exactly as split_DOS, with the only difference that splits specific requests.
Just as a last thing, we will let you figure out how update_requests works:
[17]:
plot.update_requests("Ti", color="red", linewidth=2)
We hope you enjoyed what you learned!
This next cell is just to create the thumbnail for the notebook in the docs
[18]:
thumbnail_plot = plot.update_requests("Ti", color=None, linewidth=1)
if thumbnail_plot:
thumbnail_plot.show("png")